#include "bsp_sdram.h"
#include "bsp_system_clock.h"

uint8_t bsp_sdram_config(void){
	//外设参数结构体
	exmc_sdram_parameter_struct        sdram_init_struct;
	//外设时序结构体
	exmc_sdram_timing_parameter_struct  sdram_timing_init_struct;
	//外设命令结构体
	exmc_sdram_command_parameter_struct     sdram_command_init_struct;

	//使能GPIO时钟
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOE);
	rcu_periph_clock_enable(RCU_GPIOF);
	rcu_periph_clock_enable(RCU_GPIOG);
	rcu_periph_clock_enable(RCU_GPIOC);
	//使能外设时钟
	rcu_periph_clock_enable(RCU_EXMC);
	
	//数据线GPIO配置
#if 1
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_14);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_14);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_14);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_15);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_15);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_15);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_0);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_0);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_0);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_1);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_1);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_1);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_7);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_7);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_7);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_8);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_8);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_8);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_9);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_9);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_9);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_10);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_10);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_10);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_11);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_11);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_11);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_12);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_12);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_12);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_13);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_13);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_13);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_14);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_14);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_14);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_15);
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_15);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_15);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_8);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_8);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_8);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_9);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_9);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_9);
	
	gpio_af_set(GPIOD,GPIO_AF_12,GPIO_PIN_10);
	gpio_mode_set(GPIOD,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_10);
	gpio_output_options_set(GPIOD,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_10);
#endif
	//地址线GPIO配置
#if 1
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_0);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_0);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_0);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_1);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_1);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_1);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_2);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_2);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_2);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_3);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_3);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_3);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_4);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_4);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_4);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_5);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_5);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_5);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_12);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_12);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_12);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_13);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_13);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_13);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_14);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_14);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_14);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_15);
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_15);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_15);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_0);
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_0);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_0);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_1);
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_1);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_1);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_2);
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_2);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_2);
#endif
	//控制脚GPIO配置
#if 1
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_15);//EXMC_NCAS
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_15);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_15);
	
	gpio_af_set(GPIOF,GPIO_AF_12,GPIO_PIN_11);//EXMC_NRAS
	gpio_mode_set(GPIOF,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_11);
	gpio_output_options_set(GPIOF,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_11);
	
	gpio_af_set(GPIOC,GPIO_AF_12,GPIO_PIN_2);//EXMC_SDNE
	gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_2);
	gpio_output_options_set(GPIOC,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_2);
	
	gpio_af_set(GPIOC,GPIO_AF_12,GPIO_PIN_3);//EXMC_SDCKE
	gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_3);
	gpio_output_options_set(GPIOC,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_3);
	
	gpio_af_set(GPIOC,GPIO_AF_12,GPIO_PIN_0);//EXMC_SDNWE
	gpio_mode_set(GPIOC,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_0);
	gpio_output_options_set(GPIOC,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_0);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_8);//EXMC_SDCLK
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_8);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_8);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_0);//EXMC_NBL0
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_0);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_0);
	
	gpio_af_set(GPIOE,GPIO_AF_12,GPIO_PIN_1);//EXMC_NBL1
	gpio_mode_set(GPIOE,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_1);
	gpio_output_options_set(GPIOE,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_1);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_4);//SDRAM_BS0
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_4);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_4);
	
	gpio_af_set(GPIOG,GPIO_AF_12,GPIO_PIN_5);//SDRAM_BS1
	gpio_mode_set(GPIOG,GPIO_MODE_AF,GPIO_PUPD_PULLUP,GPIO_PIN_5);
	gpio_output_options_set(GPIOG,GPIO_OTYPE_PP,GPIO_OSPEED_MAX,GPIO_PIN_5);
	
#endif
	//时序设置
	sdram_timing_init_struct.auto_refresh_delay = 8;//自刷新延时周期，待验证
	sdram_timing_init_struct.exit_selfrefresh_delay = 9;//退出自刷新延时时间最低72ns
	sdram_timing_init_struct.load_mode_register_delay = 2;//加载模式寄存器延时2个时钟周期
	sdram_timing_init_struct.row_address_select_delay = 8;//行地址选择延时周期
	sdram_timing_init_struct.row_precharge_delay = 2;//行预充电延时周期
	sdram_timing_init_struct.row_to_column_delay = 2;//行至列延时周期
	sdram_timing_init_struct.write_recovery_delay = 2;//写恢复延时周期
	
	//控制寄存器设置
	sdram_init_struct.sdram_device = EXMC_SDRAM_DEVICE0;//只有一个SDRAM芯片
	sdram_init_struct.burst_read_switch = ENABLE;
	sdram_init_struct.cas_latency = EXMC_CAS_LATENCY_3_SDCLK;//根据总线时钟配置
	sdram_init_struct.column_address_width = EXMC_SDRAM_COW_ADDRESS_9;
	sdram_init_struct.data_width = EXMC_SDRAM_DATABUS_WIDTH_16B;
	sdram_init_struct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
	sdram_init_struct.pipeline_read_delay = EXMC_PIPELINE_DELAY_2_HCLK;
	sdram_init_struct.row_address_width = EXMC_SDRAM_ROW_ADDRESS_13;
	sdram_init_struct.sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;
	sdram_init_struct.timing = &sdram_timing_init_struct;
	sdram_init_struct.write_protection = DISABLE;
	exmc_sdram_init(&sdram_init_struct);
	
	//时钟配置使能
	sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
	sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0_SELECT;//根据引脚配置设置
	sdram_command_init_struct.command = EXMC_SDRAM_CLOCK_ENABLE;//时钟使能命令
	sdram_command_init_struct.mode_register_content = 0;//模式寄存器内容
	
	uint16_t SDRAM_TIMEOUT = 0xFFFF;
	while((exmc_flag_get(EXMC_SDRAM_DEVICE0, EXMC_SDRAM_FLAG_NREADY) != RESET) && (SDRAM_TIMEOUT > 0)){//等待SDRAM控制器就绪
		SDRAM_TIMEOUT--;
	}
	if(SDRAM_TIMEOUT <= 0){//初始化失败
		goto exit;
	}
	exmc_sdram_command_config(&sdram_command_init_struct);//向SDRAM发送命令
	
	delay_ms(100);
	
	//对所有存储区预充电
	sdram_command_init_struct.command = EXMC_SDRAM_PRECHARGE_ALL;
	sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0_SELECT;
	sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;   
	sdram_command_init_struct.mode_register_content = 0;
	
	SDRAM_TIMEOUT = 0xFFFF;
	while((exmc_flag_get(EXMC_SDRAM_DEVICE0, EXMC_SDRAM_FLAG_NREADY) != RESET) && (SDRAM_TIMEOUT > 0)){//等待SDRAM控制器就绪
		SDRAM_TIMEOUT--;
	}
	if(SDRAM_TIMEOUT <= 0){//初始化失败
		goto exit;
	}
	exmc_sdram_command_config(&sdram_command_init_struct);//向SDRAM发送命令
	
	//设置自动刷新次数
	sdram_command_init_struct.command = EXMC_SDRAM_AUTO_REFRESH;
	sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0_SELECT;
	sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_9_SDCLK;   
	sdram_command_init_struct.mode_register_content = 0;
	SDRAM_TIMEOUT = 0xFFFF;
	while((exmc_flag_get(EXMC_SDRAM_DEVICE0, EXMC_SDRAM_FLAG_NREADY) != RESET) && (SDRAM_TIMEOUT > 0)){//等待SDRAM控制器就绪
		SDRAM_TIMEOUT--;
	}
	if(SDRAM_TIMEOUT <= 0){//初始化失败
		goto exit;
	}
	exmc_sdram_command_config(&sdram_command_init_struct);//向SDRAM发送命令
	
	//设置SDRAM的模式寄存器
	sdram_command_init_struct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
	sdram_command_init_struct.bank_select = EXMC_SDRAM_DEVICE0_SELECT;
	sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;   
	
	uint32_t command = 0;
	command = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | //设置突发长度
		SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型
		SDRAM_MODEREG_CAS_LATENCY_3 | //CAS值
		SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式
		SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;//设置突发写模式
	sdram_command_init_struct.mode_register_content = command;
	
	SDRAM_TIMEOUT = 0xFFFF;
	while((exmc_flag_get(EXMC_SDRAM_DEVICE0, EXMC_SDRAM_FLAG_NREADY) != RESET) && (SDRAM_TIMEOUT > 0)){//等待SDRAM控制器就绪
		SDRAM_TIMEOUT--;
	}
	if(SDRAM_TIMEOUT <= 0){//初始化失败
		goto exit;
	}
	exmc_sdram_command_config(&sdram_command_init_struct);//向SDRAM发送命令
	
	//设置自动刷新间隔 ARINTV=SDRAME刷新周期/行数-20=SDRAME刷新周期(us)*SDCLKE频率/行数
	//刷新周期设置为8K时间为64ms*1000*120/(2^13)-20 = 918
	exmc_sdram_refresh_count_set(918);
	SDRAM_TIMEOUT = 0xFFFF;
	while((exmc_flag_get(EXMC_SDRAM_DEVICE0, EXMC_SDRAM_FLAG_NREADY) != RESET) && (SDRAM_TIMEOUT > 0)){//等待SDRAM控制器就绪
		SDRAM_TIMEOUT--;
	}
	if(SDRAM_TIMEOUT <= 0){//初始化失败
		goto exit;
	}
	return 0;
exit:
	return 1;
}

void sdram_write_buf(uint8_t *buf, uint32_t addr, uint32_t len){
	for(int i=0;i<len;i++){
		*(volatile uint8_t*)(SDRAM_START_ADDR+addr) = *buf;
		addr++;
		buf++;
	}
}
void sdram_read_buf(uint8_t *buf, uint32_t addr, uint32_t len){
	for(int i=0;i<len;i++){
		*buf++ = *(volatile uint8_t*)(SDRAM_START_ADDR+addr);
		addr++;
	}
}
uint8_t rx_buf[5] = {0};
uint8_t tx_buf[5] = "1234";
uint32_t addrtest = 0;
void sdram_write_read_test(void){
	sdram_write_buf(tx_buf,addrtest,sizeof(tx_buf));
	sdram_read_buf(rx_buf,addrtest,sizeof(rx_buf));
}

